package by.dezhits.liltweets.sync;

import java.util.List;

import org.json.JSONException;
import org.json.JSONObject;

import android.accounts.Account;
import android.accounts.OperationCanceledException;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SyncResult;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import by.dezhits.liltweets.ContextHolder;
import by.dezhits.liltweets.FragmentsActivity;
import by.dezhits.liltweets.R;
import by.dezhits.liltweets.api.TwitterAPI;
import by.dezhits.liltweets.content.contract.PostContract;
import by.dezhits.liltweets.content.contract.TweetContract;
import by.dezhits.liltweets.db.DBHelper;
import by.dezhits.liltweets.db.DBHelper.PostFlags;
import by.dezhits.liltweets.http.HttpManager;
import by.dezhits.liltweets.notifications.NotificationsHelper;
import by.dezhits.liltweets.task.JsonObjectTask;
import by.dezhits.liltweets.task.ListJsonObjectTask;
import by.dezhits.liltweets.task.ParamCallback;

public class TwitterSyncAdapterService extends Service {

	private static final String NEW_TWEETS = "New Tweets!";
	private static SyncAdapterImpl sSyncAdapter = null;
	private static ContentResolver mContentResolver = null;

	public TwitterSyncAdapterService() {
		super();
	}

	private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
		private Context mContext;

		public SyncAdapterImpl(Context context) {
			super(context, true);
			mContext = context;

		}

		@Override
		public void onPerformSync(Account account, Bundle extras,
				String authority, ContentProviderClient provider,
				SyncResult syncResult) {
			try {
				TwitterSyncAdapterService.performSync(mContext, account,
						extras, authority, provider, syncResult);
			} catch (OperationCanceledException e) {
			}
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		IBinder ret = null;
		ret = getSyncAdapter().getSyncAdapterBinder();
		return ret;
	}

	private SyncAdapterImpl getSyncAdapter() {
		if (sSyncAdapter == null)
			sSyncAdapter = new SyncAdapterImpl(this);
		return sSyncAdapter;
	}

	private static void performSync(final Context context, Account account,
			Bundle extras, String authority, ContentProviderClient provider,
			SyncResult syncResult) throws OperationCanceledException {
		mContentResolver = context.getContentResolver();
		loadTweets(context);
		sendPosts(context);

	}

	private static void sendPosts(final Context context) {
		Uri uri = PostContract.PostColumns.CONTENT_URI;
		Cursor cursor = mContentResolver.query(uri, null,
				PostContract.PostColumns.STATUS + "='" + PostFlags.NOT_SENT
						+ "'", null, null);
		cursor.moveToFirst();
		while (!cursor.isAfterLast()) {
			final String textToSend = cursor.getString(cursor
					.getColumnIndex(PostContract.PostColumns.TEXT));
			cursor.moveToNext();

			Uri twitterUri = Uri
					.parse(TwitterAPI.URL.TWITTER_STATUSES_UPDATE_URL);
			Uri.Builder builder = twitterUri.buildUpon();
			builder.appendQueryParameter(TwitterAPI.QueryParametr.STATUS,
					textToSend);
			String url = builder.build().toString();
			new JsonObjectTask(new ParamCallback<JSONObject>() {
				@Override
				public void onSuccess(final JSONObject p) {
					String s = "";
					try {
						s = p.getString("text");
					} catch (JSONException e) {
						// Ignoreed because s already initialized
					}
					final String text = s;
					if (p != null) {
						new Thread(new Runnable() {
							@Override
							public void run() {
								ContentValues contentValues = new ContentValues();
								contentValues.put(context.getString(R.string.data), p.toString());
								contentValues.put(context.getString(R.string.tweet_index), 0);
								contentValues.put(context.getString(R.string.tweet_count), 1);
								mContentResolver
										.insert(TweetContract.TweetsColumns.CONTENT_URI,
												contentValues);
							}
						}).start();
						new Thread(new Runnable() {
							@Override
							public void run() {
								ContentValues contentValues = new ContentValues();
								contentValues.put(context.getString(R.string.text), text);
								contentValues.put(context.getString(R.string.status),
										DBHelper.PostFlags.SENT);
								mContentResolver.insert(
										PostContract.PostColumns.CONTENT_URI,
										contentValues);
							}
						}).start();
					}
				}

				@Override
				public void onError(Throwable e) {
					String s = DBHelper.PostFlags.NOT_SENT;
					if (e.getMessage().equals(TwitterAPI.Error.FORBIDDEN)) {
						s = DBHelper.PostFlags.CANNOT_BE_SENT;
					}
					final String status = s;
					new Thread(new Runnable() {
						@Override
						public void run() {
							ContentValues contentValues = new ContentValues();
							contentValues.put(context.getString(R.string.text), textToSend);
							contentValues.put(context.getString(R.string.status), status);
							mContentResolver.insert(
									PostContract.PostColumns.CONTENT_URI,
									contentValues);
						}
					}).start();
				}

			}, HttpManager.POST).start(url);

		}
	}

	private static void loadTweets(final Context context) {
		Uri uri = TweetContract.TweetsColumns.CONTENT_URI;
		Cursor cursor = mContentResolver.query(uri, null, null, null,
				TweetContract.TweetsColumns.ID + " DESC limit 1");
		long l = 0;
		cursor.moveToFirst();
		l = cursor.getLong(cursor
				.getColumnIndex(TweetContract.TweetsColumns.ID));
		Uri twitterUri = Uri
				.parse(TwitterAPI.URL.TWITTER_STATUSES_HOME_TIMELINE_URL);
		Uri.Builder builder = twitterUri.buildUpon();
		builder.appendQueryParameter(TwitterAPI.QueryParametr.COUNT,
				TwitterAPI.MAX_TWEETS_PER_REQUEST);
		builder.appendQueryParameter(TwitterAPI.QueryParametr.INCLUDE_ENTITIES,
				context.getString(R.string.t));
		if (l != 0) {
			builder.appendQueryParameter(TwitterAPI.QueryParametr.SINCE_ID,
					String.valueOf(l));
		}
		String url = builder.build().toString();

		new ListJsonObjectTask(new ParamCallback<List<JSONObject>>() {

			@Override
			public void onSuccess(final List<JSONObject> p) {
				if (p != null) {
					final int tweetCount = p.size();

					SharedPreferences sp = ContextHolder
							.getInstance()
							.getContext()
							.getSharedPreferences(context.getString(R.string.sync_details),
									Context.MODE_PRIVATE);
					boolean activityVisible = sp.getBoolean(context.getString(R.string.activity_visible),
							false);
					if (!activityVisible) {
						int count = sp.getInt(context.getString(R.string.count), 0);
						count += tweetCount;
						Editor editor = sp.edit();
						editor.putInt(context.getString(R.string.count), count);
						editor.commit();

						Intent notificationIntent = new Intent(context,
								FragmentsActivity.class);
						PendingIntent pIntent = PendingIntent.getActivity(
								context, 0, notificationIntent, 0);
						NotificationCompat.Builder nb = new NotificationCompat.Builder(
								ContextHolder.getInstance().getContext())
								.setSmallIcon(android.R.drawable.star_on)
								.setContentTitle(NEW_TWEETS)
								.setContentText(String.valueOf(count))
								.setContentIntent(pIntent);
						NotificationManager nm = (NotificationManager) ContextHolder
								.getInstance().getContext()
								.getSystemService(Context.NOTIFICATION_SERVICE);
						nm.notify(NotificationsHelper.SYNC_SERVICE, nb.build());
					}
					new Thread(new Runnable() {

						@Override
						public void run() {
							int tweetIndex = 0;
							for (JSONObject jsonObject : p) {
								ContentValues contentValues = new ContentValues();
								contentValues.put(context.getString(R.string.data), jsonObject.toString());
								contentValues.put(context.getString(R.string.tweet_index), tweetIndex);
								contentValues.put(context.getString(R.string.tweet_count), tweetCount);
								mContentResolver
										.insert(TweetContract.TweetsColumns.CONTENT_URI,
												contentValues);
								tweetIndex++;
							}
						}
					}).start();

				}
			}

			@Override
			public void onError(Throwable e) {

			}
		}, HttpManager.GET).start(url);
	}

}
